using Infrastructure.Attribute;
using Infrastructure.Extensions;
using JTZY.Model.Business.Dto;
using JTZY.Model.Business;
using JTZY.Repository;
using JTZY.Service.Business.IBusinessService;
using static JTZY.Common.WxNoticeHelper;
using Microsoft.Extensions.DependencyInjection;
using Infrastructure.Enums;
using Infrastructure;
using static JTZY.Common.GlobalEnumVars;
using JTZY.Model.Financial;
using Mapster;
using JTZY.Model.Financial.Dto;
using JTZY.Model.Goods;

namespace JTZY.Service.Business
{
    /// <summary>
    /// 用户余额表Service业务层处理
    /// </summary>
    [AppService(ServiceType = typeof(ICorecmsuserbalanceService), ServiceLifetime = LifeTime.Transient)]
    public class CorecmsuserbalanceService : BaseService<Corecmsuserbalance>, ICorecmsuserbalanceService
    {
        private readonly IServiceProvider _serviceProvider;

        public CorecmsuserbalanceService(IServiceProvider serviceProvider)
        {
            _serviceProvider = serviceProvider;
        }
        /// <summary>
        /// 导出提现记录
        /// </summary>
        /// <param name="parm"></param>
        /// <returns></returns>
        public PagedInfo<CorecmsuserbalanceDto> ExportList(CorecmsuserbalanceQueryDto parm)
        {
            var predicate = QueryExp(parm);
            var query = Queryable()
                //.Includes(x=>x.CorecmsuserNav)
                .Where(predicate.ToExpression())
                .Where(x => x.UserId == parm.userId);
            var response = query
                .LeftJoin<Corecmsproducts>((balance, prod) => balance.ProductId == prod.Id)
                .OrderByDescending(balance => balance.CreateTime)
                 .Select((balance, prod) => new CorecmsuserbalanceDto()
                 {
                     Id = balance.Id,
                     UserId = balance.UserId,
                     Type = balance.Type,
                     Money = balance.Money,
                     Balance = balance.Balance,
                     SourceId = balance.SourceId,
                     Memo = balance.Memo,
                     CreateTime = balance.CreateTime,
                     ProductId = balance.ProductId,
                     sn = prod.Sn,
                     Addon = balance.Addon,
                     ImageUrl = balance.ImageUrl,
                     Nums = balance.Nums,
                 })
                 .ToPage<CorecmsuserbalanceDto>(parm); ;
            return response;
        }
        /// <summary>
        /// 查询用户余额表列表
        /// </summary>
        /// <param name="parm"></param>
        /// <returns></returns>
        public PagedInfo<CorecmsuserbalanceDto> GetList(CorecmsuserbalanceQueryDto parm)
        {
            var predicate = QueryExp(parm);

            var query = Queryable()
                //.Includes(x=>x.CorecmsuserNav)
                .Where(predicate.ToExpression())
                .Where(x => x.UserId == parm.userId);
            var query2 = Queryable()
               //.Includes(x=>x.CorecmsuserNav)
               .Where(predicate.ToExpression())
               .Where(x => x.UserId == parm.userId);
            var total = query2.GroupBy(e => e.Type).Select(e => new CorecmsuserbalanceDto()
            {
                Type = e.Type,
                Money = SqlFunc.AggregateSum(e.Money),
                InNums = SqlFunc.AggregateCount(e),
            }).ToList();
            var response = query
                .LeftJoin<Corecmsproducts>((balance,prod)=>balance.ProductId==prod.Id)
               
                .OrderByDescending(balance => balance.Id)
                 .Select((balance, prod) => new CorecmsuserbalanceDto() { 
                   Id = balance.Id,
                   UserId = balance.UserId,
                   Type = balance.Type,
                   Money = balance.Money,
                   Balance = balance.Balance,
                   SourceId = balance.SourceId,
                   Memo = balance.Memo,
                   CreateTime = balance.CreateTime,
                   ProductId = balance.ProductId,
                   sn = prod.Sn,
                   Addon = balance.Addon,
                   ImageUrl = balance.ImageUrl,
                   Nums = balance.Nums,
                 })
                 .ToPage<CorecmsuserbalanceDto>(parm);
            var first = response.Result.FirstOrDefault();
           
            foreach (var item in total)
            {
                
                switch(item.Type)
                {
                    case 9:
                    case 12:
                        first.InAmount += item.Money;
                        first.InNums += item.InNums;
                        break;
                    case 11://售后退款
                        first.OutAmount += item.Money;
                        first.OutNums += item.InNums;
                        break;
                    case 4:
                        first.OutAmount += item.Money;
                        first.OutNums += item.InNums;
                        break;
                }
                //item.CorecmsuserNav.PassWord = "";
            }
            return response;
        }


        /// <summary>
        /// 获取详情
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        public Corecmsuserbalance GetInfo(int Id)
        {
            var response = Queryable()
                .Where(x => x.Id == Id)
                .First();

            return response;
        }

        /// <summary>
        /// 添加用户余额表
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public Corecmsuserbalance AddCorecmsuserbalance(Corecmsuserbalance model)
        {
            return Insertable(model).ExecuteReturnEntity();
        }

        /// <summary>
        /// 修改用户余额表
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public int UpdateCorecmsuserbalance(Corecmsuserbalance model)
        {
            return Update(model, true);
        }

        /// <summary>
        /// 余额变动记录
        /// </summary>
        /// <param name="userId">当前用户id,当是店铺的时候，取店铺创始人的userId</param>
        /// <param name="type">类型</param>
        /// <param name="money">金额，永远是正的</param>
        /// <param name="sourceId">资源id</param>
        /// <param name="cateMoney">服务费金额 (提现)</param>
        /// <returns></returns>
        public async Task<WebApiCallBack> Change(long userId, int type, decimal money, string sourceId = "", decimal cateMoney = 0)
        {
            using var container = _serviceProvider.CreateScope();
            var userServices = container.ServiceProvider.GetService<ICorecmsuserService>();

            var jm = new WebApiCallBack();

            if (money != 0)
            {
                try
                {
                    UseTran(() =>
                    {
                        //取用户实际余额
                        //(会员陌小北提供)
                        var userInfo = userServices.GetById(userId);

                        if (userInfo == null)
                        {
                            jm.data = jm.code = 11004;
                            jm.msg = "非法用户";
                            return;
                        }

                        //取描述，并简单校验
                        var res = UserHelper.GetMemo(type, money, cateMoney);
                        if (string.IsNullOrEmpty(res))
                        {
                            return;
                        }
                        var memo = res;
                        //如果是减余额的操作，还是加余额操作
                        if (type is (int)UserBalanceSourceTypes.Pay or (int)UserBalanceSourceTypes.Tocash)
                        {
                            money = -money - cateMoney;
                        }

                        var balance = userInfo.Balance + money;
                        if (balance < 0)
                        {
                            jm.data = jm.code = 11007;
                            jm.msg = "余额不足";
                            return;
                        }
                        var balanceModel = new Corecmsuserbalance();
                        balanceModel.UserId = userId;
                        balanceModel.Type = type;
                        balanceModel.Money = money;
                        balanceModel.Balance = balance;
                        balanceModel.SourceId = sourceId;
                        balanceModel.Memo = memo;
                        balanceModel.CreateTime = DateTime.Now;


                        //增加记录
                        var balanceModelId = InsertReturnIdentity(balanceModel);
                        balanceModel.Id = balanceModelId;
                        //更新用户数据
                        bool updateRes = userServices.Update(p => new Corecmsuser() { Balance = balance }, p => p.Id == userId && p.Balance == userInfo.Balance);
                        jm.status = updateRes;
                        jm.data = balanceModel;
                    });
                }
                catch (Exception e)
                {
                    jm.status = false;

                }
            }
            jm.status = true;

            return jm;
        }

        /// <summary>
        /// 查询导出表达式
        /// </summary>
        /// <param name="parm"></param>
        /// <returns></returns>
        private static Expressionable<Corecmsuserbalance> QueryExp(CorecmsuserbalanceQueryDto parm)
        {
            var predicate = Expressionable.Create<Corecmsuserbalance>();
            predicate = predicate.AndIF(parm.beginCreateTime == null, it => it.CreateTime >= DateTime.Now.AddDays(-30).ToShortDateString().ParseToDateTime());
            predicate = predicate.AndIF(parm.beginCreateTime != null, it => it.CreateTime >= parm.beginCreateTime);
            predicate = predicate.AndIF(parm.endCreateTime != null, it => it.CreateTime <= parm.endCreateTime);

            if (!string.IsNullOrEmpty(parm.biztype))
            {
                var biztypes = parm.biztype.Split(',').ToList();
                predicate.And(it => biztypes.Contains(it.Type.ToString()));
            }
            if (!string.IsNullOrEmpty(parm.typesAccount))
            {
                var acctypes = parm.typesAccount.Split(',').ToList();
                if (acctypes.Contains("00"))
                {
                    acctypes.Add("9");
                    acctypes.Add("12");
                }
                if (acctypes.Contains("11"))
                {
                    acctypes.Add("4");
                    acctypes.Add("11");
                }
                predicate.And(it => acctypes.Contains(it.Type.ToString()));
            }

            return predicate;
        }
    }
}